#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include "../vcd-log.h"
#include "../vcd-crypto.h"
#include "vcd-conf.h"

struct vcd_conf* g_vcd_conf = NULL;

static gchar* read_value(const char* src, const char* type);
static int read_all(void);
static int set_key_file(void);

char *get_ip_port(void)
{
    if (g_vcd_conf->local_model_check_status) {
        memset(g_vcd_conf->ip_port, 0, 40);
        strcpy(g_vcd_conf->ip_port, "127.0.0.1");
        strcat(g_vcd_conf->ip_port, ":8006");
        return g_vcd_conf->ip_port;
    }

    if (g_vcd_conf->login_mode == EMODE_NEW) {
        return g_vcd_conf->ip;
    }
    else {
        memset(g_vcd_conf->ip_port, 0, 40);
        strcpy(g_vcd_conf->ip_port, g_vcd_conf->ip);
        strcat(g_vcd_conf->ip_port, ":8006");
        return g_vcd_conf->ip_port;
    }
}

//return 0:success other: error
int read_vcd_conf(void)
{
#ifdef __WIN32__
    //windows暂时就不需要加载配置了，否则会报一大堆vcdvcdvcd错误，
    //实际上windows也就用到usb一个参数，在windows上暂时不支持记录上次勾选的usb设备
    return 0;
#endif

    g_vcd_conf = g_malloc0(sizeof(struct vcd_conf));
    if (g_vcd_conf == NULL) {
        LOG_ERROR("g_vcd_conf init error!");
        return -1;
    }

    memset(g_vcd_conf, 0, sizeof(struct vcd_conf));

    GKeyFile *keyfile = NULL;
    gchar *conf_file = NULL;
    GError *error = NULL;
    int res = 0;

    keyfile = g_key_file_new();
    if (keyfile == NULL) {
        LOG_ERROR("keyfile init error!");
        return -1;
    }

    // todo fengfeng
#if defined (__linux__)
    const gchar* path = g_get_user_config_dir();
#elif defined (__WIN32__)
    char tmp[500] = {0};
    char* curr = g_get_current_dir();
    strcat(tmp, curr);
    strcat(tmp, "\\..\\share");
    char* path = tmp;
#else
     char* path = g_get_user_config_dir();
#endif

    int mode = S_IRWXU;
    conf_file = g_build_filename(path, "spicy", NULL);
    if (g_mkdir_with_parents(conf_file, mode) == -1) {
         LOG_ERROR("failed to create config directory");
         goto fail;
    }
    g_free(conf_file);

    conf_file = g_build_filename(path, "spicy", "vcd-settings", NULL);
    if (!g_key_file_load_from_file(keyfile, conf_file, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) {
        LOG_ERROR("Couldn't load configuration: %s", error->message);
        g_clear_error(&error);
        //如果暂时没有配置文件，下面做记录时会创建，所以不能goto fail
        //goto fail;
    }

    g_vcd_conf->keyfile = keyfile;
    g_vcd_conf->conf_file = conf_file;

    res = read_all();
    if (res != 0) {
        LOG_ERROR("read_all error");
        goto fail;
    }

    return 0;//success
fail:
    if (keyfile) {
        g_key_file_free(keyfile);
        keyfile = NULL;
    }
    G_SAFE_FREE(conf_file)
    if (error) {
        g_clear_error(&error);
        error = NULL;
    }
    return -1;//fail
}

int reload_vcd_conf(void)
{
    return read_all();
}

static gchar* read_value(const char* src, const char* type)
{
    GError *error = NULL;
    gchar *str = NULL;
    str = g_key_file_get_string(g_vcd_conf->keyfile, type, src, &error);
    if (error == NULL) {
        M_DEBUG("read config %s = %s", src, str);
        return str;
    } else {
        LOG_ERROR("%s", error->message);
        g_error_free(error);
        return NULL;
    }
}

static int read_all(void)
{
    gchar* str = NULL;
    struct vcd_conf* cf = g_vcd_conf;

    cf->login_mode = EMODE_OLD;
    str = read_value("login-mode", "vcd");
    if (str != NULL) {
        if (strcmp(str, "EMODE_NEW") == 0)
            cf->login_mode = EMODE_NEW;
        G_SAFE_FREE(str);
    }

    str = read_value("ip", "vcd");
    if (str != NULL) {
        snprintf(cf->ip, sizeof(cf->ip), "%s", str);
        G_SAFE_FREE(str);
    }

    str = read_value("username", "vcd");
    if (str != NULL) {
        snprintf(cf->username, sizeof(cf->username), "%s", str);
        G_SAFE_FREE(str);
    }

    str = read_value("node", "vcd");
    if (str != NULL) {
        snprintf(cf->node, sizeof(cf->node), "%s", str);
        G_SAFE_FREE(str);
    }

    str = read_value("vmid", "vcd");
    if (str != NULL) {
        cf->vmid = (gint64)atoll(str);
        G_SAFE_FREE(str);
    }

    str = read_value("public-id", "vcd");
    if (str != NULL) {
        snprintf(cf->public_id, sizeof(cf->public_id), "%s", str);
        G_SAFE_FREE(str);
    }

    cf->bitrate = 4;
    str = read_value("bitrate", "vcd");
    if (str != NULL) {
        cf->bitrate = (gint64)atoll(str);
        G_SAFE_FREE(str);
    }

    cf->fresh_ticket_interval = 1200;
    str = read_value("fresh_ticket_interval", "vcd");
    if (str != NULL) {
        gint64 interval = (gint64)atoll(str);
        if (interval < 1)
            interval = 1;
        cf->fresh_ticket_interval = interval;
        G_SAFE_FREE(str);
    }

    cf->fresh_vm_list_interval = 15;
    str = read_value("fresh_vm_list_interval", "vcd");
    if (str != NULL) {
        gint64 interval = (gint64)atoll(str);
        if (interval < 1)
            interval = 1;
        cf->fresh_vm_list_interval = interval;
        G_SAFE_FREE(str);
    }

    str = read_value("passwd", "vcd");
    if (str != NULL) {
        snprintf(cf->passwd, sizeof(cf->passwd), "%s", str);
        G_SAFE_FREE(str);
    }

    cf->enable_user_passwd = 1;
    str = read_value("if-enable-user-passwd", "vcd");
    if(str != NULL){
        if (strcmp(str, "DISABLE") == 0) {
            cf->enable_user_passwd = 0;
        }
        G_SAFE_FREE(str);
    }

    cf->enable_grade = 0;
    str = read_value("if-enable-grade", "vcd");
    if(str != NULL){
        if (strcmp(str, "ENABLE") == 0) {
            cf->enable_grade = 1;
        }
        G_SAFE_FREE(str);
    }

    cf->login_way = PRIVATE_LOGIN;
    str = read_value("login-way", "vcd");
    if (str != NULL) {
        if (strcmp(str, "PUBLIC") == 0)
            cf->login_way = PUBLIC_LOGIN;
        G_SAFE_FREE(str);
    }

    str = read_value("sys-passwd", "vcd");
    if (str != NULL) {
        snprintf(cf->sys_passwd, sizeof(cf->sys_passwd), "%s", str);
        G_SAFE_FREE(str);
    }

    str = read_value("sound-card-name", "vcd");
    if (str != NULL) {
        snprintf(cf->sound_card_name, sizeof(cf->sound_card_name), "%s", str);
        G_SAFE_FREE(str);
    }

    str = read_value("if-autologin", "vcd");
    if (str != NULL) {
        if (strcmp(str, "YES") == 0)
            cf->enable_autologin = 1;
        G_SAFE_FREE(str);
    }

    str = read_value("rdp", "vcd");
    if (str != NULL) {
        if (strcmp(str, "YES") == 0)
            cf->enable_rdp = 1;
        G_SAFE_FREE(str);
    }

    cf->usb_redir_apply_all_flag = TRUE;
    str = read_value("usb-redir-apply-all", "vcd");
    if (str != NULL) {
        if (strcmp(str, "true") == 0)
            cf->usb_redir_apply_all_flag = TRUE;
        G_SAFE_FREE(str);
    }

    cf->local_model_check_status = FALSE;
    str = read_value("local-model-check-status", "vcd");
    if (str != NULL) {
        if (strcmp(str, "true") == 0)
            cf->local_model_check_status = TRUE;
        if (strcmp(str, "1") == 0)
            cf->local_model_check_status = TRUE;
        if (strcmp(str, "YES") == 0)
            cf->local_model_check_status = TRUE;
        G_SAFE_FREE(str);
    }

    cf->topbar_position = POSITION_TOP;
    str = read_value("topbar-position", "vcd");
    if (str != NULL) {
        if (strcmp(str, "left") == 0)
            cf->topbar_position = POSITION_LEFT;
        if (strcmp(str, "top") == 0)
            cf->topbar_position = POSITION_TOP;
        if (strcmp(str, "right") == 0)
            cf->topbar_position = POSITION_RIGHT;
        G_SAFE_FREE(str);
    }

    cf->is_show_topbar = TRUE;
    str = read_value("is-show-topbar", "vcd");
    if (str != NULL) {
        if (strcmp(str, "false") == 0)
            cf->is_show_topbar = FALSE;
        if (strcmp(str, "0") == 0)
            cf->is_show_topbar = FALSE;
        if (strcmp(str, "NO") == 0)
            cf->is_show_topbar = FALSE;
        if (strcmp(str, "FALSE") == 0)
            cf->is_show_topbar = FALSE;
        G_SAFE_FREE(str);
    }
    return 0;
}

static int set_key_file(void)
{
    const char* str = NULL;
    struct vcd_conf* cf = g_vcd_conf;

    str = (cf->login_mode == EMODE_NEW ? "EMODE_NEW" : "EMODE_OLD");
    g_key_file_set_string(cf->keyfile, "vcd", "login-mode", str);

    g_key_file_set_string(cf->keyfile, "vcd", "ip", cf->ip);

    g_key_file_set_string(cf->keyfile, "vcd", "username", cf->username);

    g_key_file_set_string(cf->keyfile, "vcd", "node", cf->node);

    g_key_file_set_int64(cf->keyfile, "vcd", "vmid", cf->vmid);

    g_key_file_set_string(cf->keyfile, "vcd", "public-id", cf->public_id);

    g_key_file_set_int64(cf->keyfile, "vcd", "fresh_ticket_interval", cf->fresh_ticket_interval);

    g_key_file_set_int64(cf->keyfile, "vcd", "fresh_vm_list_interval", cf->fresh_vm_list_interval);

    g_key_file_set_int64(cf->keyfile, "vcd", "bitrate", cf->bitrate);

    g_key_file_set_string(cf->keyfile, "vcd", "passwd", cf->passwd);

    str = (cf->enable_user_passwd ? "ENABLE" : "DISABLE");
    g_key_file_set_string(cf->keyfile, "vcd", "if-enable-user-passwd", str);

    str = (cf->enable_grade ? "ENABLE" : "DISABLE");
    g_key_file_set_string(cf->keyfile, "vcd", "if-enable-grade", str);

    str = (cf->login_way == PRIVATE_LOGIN ? "PRIVATE" : "PUBLIC");
    g_key_file_set_string(cf->keyfile, "vcd", "login-way", str);

    g_key_file_set_string(cf->keyfile, "vcd", "sys-passwd", cf->sys_passwd);

    g_key_file_set_string(cf->keyfile, "vcd", "sound-card-name", cf->sound_card_name);

    str = (cf->enable_autologin ? "YES" : "NO");
    g_key_file_set_string(cf->keyfile, "vcd", "if-autologin", str);

    str = (cf->enable_rdp ? "YES" : "NO");
    g_key_file_set_string(cf->keyfile, "vcd", "rdp", str);

    g_key_file_set_boolean(cf->keyfile, "vcd", "usb-redir-apply-all", cf->usb_redir_apply_all_flag);

    g_key_file_set_boolean(cf->keyfile, "vcd", "local-model-check-status", cf->local_model_check_status);

    str = "top";
    if(cf->topbar_position == POSITION_LEFT)
        str = "left";
    else if(cf->topbar_position == POSITION_RIGHT)
        str = "right";
    g_key_file_set_string(cf->keyfile, "vcd", "topbar-position", str);

    g_key_file_set_boolean(cf->keyfile, "vcd", "is-show-topbar", cf->is_show_topbar);

    return 0;
}


int update_vcd_conf(void)
{
    if(set_key_file() != 0){
        return -1;
    }

    struct vcd_conf* cf = g_vcd_conf;
    GError *error = NULL;
    if(!g_key_file_save_to_file(cf->keyfile, cf->conf_file, &error)){
        LOG_ERROR("Couldn't save configuration: %s", error->message);
        g_error_free(error);
        error = NULL;
        return -1;
    }

    return 0;
}

gboolean vraify_localmode_user_pass(const char* key, const char *pass)
{
    GKeyFile *keyfile = NULL;
    gchar *conf_file = NULL;
    GError *error = NULL;
    int res = 0;

    keyfile = g_key_file_new();
    if (keyfile == NULL) {
        LOG_ERROR("keyfile init error!");
        return FALSE;
    }

    // todo fengfeng
#if defined (__linux__)
    const gchar* path = g_get_user_config_dir();
#elif defined (__WIN32__)
    char tmp[500] = {0};
    char* curr = g_get_current_dir();
    strcat(tmp, curr);
    strcat(tmp, "\\..\\share");
    char* path = tmp;
#else
     char* path = g_get_user_config_dir();
#endif

    int mode = S_IRWXU;
    conf_file = g_build_filename(path, "spicy", NULL);
    if (g_mkdir_with_parents(conf_file, mode) == -1) {
         LOG_ERROR("failed to create config directory");
         return FALSE;
    }
    g_free(conf_file);

    conf_file = g_build_filename(path, "spicy", "vcd-settings", NULL);
    if (!g_key_file_load_from_file(keyfile, conf_file, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) {
        LOG_ERROR("Couldn't load configuration: %s", error->message);
        g_clear_error(&error);
        //如果暂时没有配置文件，下面做记录时会创建，所以不能goto fail
        //goto fail;
    }

    char decode_out[1024] = {0};

    gchar *str = NULL;
    str = g_key_file_get_string(keyfile, "user-pass", key, &error);
    if (error == NULL) {
        
        vcd_decode_crypto(str, decode_out);
        M_DEBUG("read config %s = %s  decode out = %s, pass = %s", key, str, decode_out, pass);

        if (strcmp(decode_out, pass) == 0) {
            if (keyfile) {
                g_key_file_free(keyfile);
                keyfile = NULL;
            }
            G_SAFE_FREE(conf_file)
            if (error) {
                g_clear_error(&error);
                error = NULL;
            }
            G_SAFE_FREE(str);
            return TRUE;
        }

    } else {
        LOG_ERROR("%s", error->message);
    }

    if (keyfile) {
        g_key_file_free(keyfile);
        keyfile = NULL;
    }
    G_SAFE_FREE(conf_file)
    if (error) {
        g_clear_error(&error);
        error = NULL;
    }
    return FALSE;//fail
}

void heartbeat_record_user_pass_config(LocalmodeUserPass* user_pass, int count)
{

    GKeyFile *keyfile = NULL;
    gchar *conf_file = NULL;
    GError *error = NULL;
    int res = 0;

    keyfile = g_key_file_new();
    if (keyfile == NULL) {
        LOG_ERROR("keyfile init error!");
        return;
    }

    // todo fengfeng
#if defined (__linux__)
    const gchar* path = g_get_user_config_dir();
#elif defined (__WIN32__)
    char tmp[500] = {0};
    char* curr = g_get_current_dir();
    strcat(tmp, curr);
    strcat(tmp, "\\..\\share");
    char* path = tmp;
#else
     char* path = g_get_user_config_dir();
#endif

    int mode = S_IRWXU;
    conf_file = g_build_filename(path, "spicy", NULL);
    if (g_mkdir_with_parents(conf_file, mode) == -1) {
         LOG_ERROR("failed to create config directory");
         return;
    }
    g_free(conf_file);

    conf_file = g_build_filename(path, "spicy", "vcd-settings", NULL);
    if (!g_key_file_load_from_file(keyfile, conf_file, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) {
        LOG_ERROR("Couldn't load configuration: %s", error->message);
        g_clear_error(&error);
        //如果暂时没有配置文件，下面做记录时会创建，所以不能goto fail
        //goto fail;
    }

    //删除用户名密码
    g_key_file_remove_group(keyfile, "user-pass", &error);
    if (error != NULL) {
        g_clear_error(&error);
        error = NULL;
    }

    if (count == 0) {
    } else {
        for (int i = 0; i < count; ++i) {
            LocalmodeUserPass* one = user_pass + i;
            g_key_file_set_string(keyfile, "user-pass", one->username, one->password);
            //M_DEBUG("username=%s, password=%s\n", one->username, one->password);
        }
        if (!g_key_file_save_to_file(keyfile, conf_file, &error)){
            LOG_ERROR("Couldn't save configuration: %s", error->message);
        }
    }

    if (keyfile) {
        g_key_file_free(keyfile);
        keyfile = NULL;
    }
    G_SAFE_FREE(conf_file)
    G_SAFE_FREE(user_pass)
    if (error) {
        g_clear_error(&error);
        error = NULL;
    }
}